<?php
// +----------------------------------------------------------------------
// | sfadmin - Suifeng Administration
// +----------------------------------------------------------------------
// | Copyright (c) 2017-2020 http://suifeng.tech All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: suifeng <1787585212@qq.com>
// +----------------------------------------------------------------------

namespace suifeng\admin;

use suifeng\Csrf;
use suifeng\admin\AdminHtml;
use suifeng\utils\HtmlUtil;

final class AdminForm
{
//     public $array = array();
//     public $errors = array();

//     public function __construct($array = null, $errors = null)
//     {
//         $this->array = $array;
//         $this->errors = $errors;
//     }

//     public function renderForm($options)
//     {
//         $submit_url = isset($options['submit_url']) ? $options['submit_url'] : null;
//         $cancel_url = isset($options['cancel_url']) ? $options['cancel_url'] : null;
//         $controls = isset($options['controls']) ? $options['controls'] : array();

//         unset($options['submit_url'], $options['cancel_url'], $options['controls']);

// //         $attributes['class'] = 'form';
// //         $attributes['method'] = 'post';
// //         $attributes['action'] = $submit_url;
//         $html = '';//HtmlUtil::render_start_tag('form', $attributes);

//         foreach ($controls as $field => $config) {
//             if (isset($config['control'])) {
//                 $control = $config['control'];
//                 unset($config['control']);
//             } else {
//                 $control = 'text';
//             }

//             if (isset($config['label'])) {
//                 $label = $config['label'];
//                 unset($config['label']);
//             } else {
//                 $label = strtoupper($field);
//             }

//             if (isset($config['help'])) {
//                 $help = $config['help'];
//                 unset($config['help']);
//             } else {
//                 $help = null;
//             }

//             $html .= $this->renderGroup($field, $label, $help, $control, $config);
//         }

//         $html .= HtmlUtil::render_tag('div', array('class' => 'form-group form-actions'), $this->renderSubmitAndCancel($submit_url, $cancel_url));
// //         $html .= HtmlUtil::render_end_tag('form');

//         return $html;
//     }

//     public function renderGroup($field, $label, $help, $control, $options = array())
//     {
//         $control_html = $this->renderControl($field, $label, $help, $control, $options);

//         $attributes['class'] = 'form-group' . ($this->hasError($field) ? ' has-error' : '');
//         return HtmlUtil::render_tag('div', $attributes, $control_html);
//     }

//     public function renderControl($field, $label, $help, $control, $options = array())
//     {
//         $label_html = $this->renderLabel($label, array('for' => $field));
//         $help_html = $help ? $this->renderHelp($help) : null;
//         $error_html = $this->hasError($field) ? $this->renderError($this->errors[$field]) : null;

//         $control_method = 'render' . ucfirst($control);
//         $control_html = $this->$control_method($field, $options);

//         return $label_html . $control_html . $help_html . $error_html;
//     }

//     private function _renderInput($type, $name, $value, $attributes = array())
//     {
//         $attributes['type'] = $type;
//         $attributes['name'] = $name;
//         $attributes['value'] = $value;
//         return HtmlUtil::render_tag('input', $attributes);
//     }

//     public function renderHidden($field, $options = array())
//     {
//         return $this->_renderInput('hidden', $field, $this->getValue($field), $options);
//     }

//     public function renderText($field, $options = array())
//     {
//         $attributes['class'] = 'form-control';
//         $attributes = array_merge($attributes, $options);
//         return $this->_renderInput('text', $field, $this->getValue($field), $attributes);
//     }

//     public function renderPassword($field, $options = array())
//     {
//         $attributes['class'] = 'form-control';
//         $attributes = array_merge($attributes, $options);
//         return $this->_renderInput('password', $field, $this->getValue($field), $attributes);
//     }

//     public function renderUrl($field, $options = array())
//     {
//         $attributes['class'] = 'form-control';
//         $attributes = array_merge($attributes, $options);
//         return $this->_renderInput('url', $field, $this->getValue($field), $attributes);
//     }

//     public function renderEmail($field, $options = array())
//     {
//         $attributes['class'] = 'form-control';
//         $attributes = array_merge($attributes, $options);
//         return $this->_renderInput('email', $field, $this->getValue($field), $attributes);
//     }

//     public function renderDecimal($field, $options = array())
//     {
//         $attributes['class'] = 'form-control format format-decimal';
//         $attributes = array_merge($attributes, $options);
//         return $this->_renderInput('text', $field, $this->getValue($field), $attributes);
//     }

//     public function renderNumber($field, $options = array())
//     {
//         $attributes['class'] = 'form-control format format-number';
//         $attributes = array_merge($attributes, $options);
//         return $this->_renderInput('text', $field, $this->getValue($field), $attributes);
//     }

//     public function renderDate($field, $options = array())
//     {
//         $attributes['class'] = 'form-control';
//         $attributes['control'] = 'datetime-picker';
//         $attributes['data-format'] = config('SYS_DATE_FORMAT');
//         $attributes['value'] = $this->getValue($field);
//         $attributes = array_merge($attributes, $options);
//         return $this->_renderInput('text', $field, $this->formatValue($field, $options), $attributes);
//     }

//     public function renderTsdate($field, $options = array())
//     {
//         $attributes['class'] = 'form-control';
//         $attributes['control'] = 'datetime-picker';
//         $attributes['ref-hidden'] = $field;
//         $attributes['data-format'] = config('SYS_DATE_FORMAT');
//         $attributes['value'] = sf_format_date($this->getValue($field));
//         $attributes = array_merge($attributes, $options);
//         $input_html = HtmlUtil::render_tag('input', $attributes);
//         $hidden_html = $this->renderHidden($field);
//         return $input_html . $hidden_html;
//     }

//     public function renderColor($field, $options = array())
//     {
//         $attributes['class'] = 'form-control';
//         $attributes = array_merge($attributes, $options);
//         return $this->_renderInput('color', $field, $this->getValue($field), $attributes);
//     }

//     public function renderSwitch($field, $options = array())
//     {
//         $attributes['type'] = 'checkbox';
//         $attributes['switch-ref'] = $field;
//         if ($this->getValue($field)) {
//             $attributes['checked'] = 'checked';
//         }
//         $attributes = array_merge($attributes, $options);
//         $input_html = HtmlUtil::render_tag('input', $attributes);
//         $hidden_html = $this->renderHidden($field);
//         return HtmlUtil::render_tag('div', array('class' => 'sf-switch'), $input_html) . $hidden_html;
//     }

//     public function renderImage($field, $options = array())
//     {
//         //$options['data-preview-file-type'] = 'image';
// //         $options['data-allowed-file-types'] = 'image';
// //         $options['data-allowed-file-extensions'] = 'gif';
//         return $this->renderFile($field, $options);
//     }

//     public function renderFile($field, $options = array())
//     {
//         $attributes['type'] = 'file';
//         $attributes['control'] = 'bootstrap-fileinput';
//         $attributes['ref-hidden'] = $field;
//         $attributes['data-max-file-count'] = 1;
//         list($file_ids, $file_list) = $this->_getFileList($this->getValue($field));
//         $attributes['initial-file-list'] = $file_list;
//         $attributes = array_merge($attributes, $options);
//         $input_html = HtmlUtil::render_tag('input', $attributes);
//         $hidden_html = $this->renderHidden($field, array('value' => $file_ids));
//         return $input_html . $hidden_html;
//     }

//     private function _getFileList($value)
//     {
//         $file_list = array();
//         $file_ids = array();
//         foreach (explode(',', $value) as $file_id) {
//             $file_info = model('admin/upload')->getFileInfo($file_id);
//             if ($file_info) {
//                 $file_ids[] = $file_info['id'];
//                 $file_list[] = implode(',', array($file_info['id'], $file_info['name'], $file_info['size'], $file_info['url']));
//             }
//         }
//         return array(implode(',', $file_ids), implode(';', $file_list));
//     }

//     public function renderHtml($field, $options = array())
//     {
//         $attributes['control'] = 'summernote';
//         $attributes['ref-hidden'] = $field;
//         $attributes['data-height'] = '300';
//         $attributes = array_merge($attributes, $options);
//         $div_html = HtmlUtil::render_tag('div', $attributes, $this->getValue($field));
//         $hidden_html = $this->renderHidden($field);
//         return $div_html . $hidden_html;
//     }

//     public function renderTextarea($field, $options = array())
//     {
//         $attributes['name'] = $field;
//         $attributes['class'] = 'form-control';
//         $attributes['rows'] = 10;
//         $attributes = array_merge($attributes, $options);
//         return HtmlUtil::render_tag('textarea', $attributes, $this->getValue($field));
//     }

//     public function getValue($field)
//     {
//         if (isset($this->array[$field])) {
//             return $this->array[$field];
//         } else {
//             return null;
//         }
//     }

//     public function formatValue($field, $options)
//     {
//         $value = $this->getValue($field);
//         $format = isset($options['format']) ? $options['format'] : '';
//         foreach (explode(',', $format) as $fun) {
//             if (function_exists($fun)) {
//                 $value = $fun($value);
//             }
//         }
//         return $value;
//     }

//     public function hasError($field)
//     {
//         return isset($this->errors[$field]);
//     }

//     public function renderLabel($label, $options = array())
//     {
//         $attributes = $options;
//         $attributes['class'] = 'control-label';
//         return HtmlUtil::render_tag('label', $attributes, $label . '：');
//     }

//     public function renderHelp($help, $options = array())
//     {
//         $attributes = $options;
//         $attributes['class'] = 'help-block';
//         return HtmlUtil::render_tag('span', $attributes, $help);
//     }

//     public function renderError($error, $options = array())
//     {
//         $attributes = $options;
//         $attributes['class'] = 'help-block error';
//         return HtmlUtil::render_tag('span', $attributes, $error);
//     }

//     public function renderButton($text, $icon, $class, $options = array())
//     {
//         $icon_html = $icon ? HtmlUtil::render_tag('i', array('class' => $icon)) : null;

//         $attributes = $options;
//         $attributes['type'] = 'button';
//         $attributes['class'] = $class;
//         return HtmlUtil::render_tag('button', $attributes, $icon_html . '&nbsp;&nbsp;' . $text . '&nbsp;&nbsp;');
//     }

//     public function renderSubmitAndCancel($submit_url, $cancel_url)
//     {
//         $submit_html = $this->renderButton('确定', null, 'btn btn-primary btn-submit ajax-post required-validate', array('url' => $submit_url));
//         $cancel_html = $this->renderButton('取消', null, 'btn btn-default btn-cancel redirect', array('url' => $cancel_url));
//         return $submit_html . '&nbsp;' . $cancel_html;
//     }

//     public function renderActions($submit_url, $cancel_url)
//     {
//         return HtmlUtil::render_tag('div', array('class' => 'form-group form-actions'), $this->renderSubmitAndCancel($submit_url, $cancel_url));
//     }

    private static $csrf_hidden_name = '_ft';
    private static $controls_hidden_name = '_fc';

    public static function render_csrf_token($key = '')
    {
        return self::render_hidden(self::$csrf_hidden_name, Csrf::generate($key));
    }

    public static function handle_post()
    {
        $post = request()->post();
        $data = array();

        foreach (array_keys($post) as $name) {
            if (substr($name, 0, 1) != '_') {
                $data[$name] = $post[$name];
            }
        }

        if (isset($post[self::$controls_hidden_name])) {
            foreach ((array) $post[self::$controls_hidden_name] as $name) {
                self::_ensure_exists($data, $name);
            }
        }

        return $data;
    }

    private static function _ensure_exists(&$array, $name)
    {
        if (($pos = strpos($name, '[')) !== false) {
            $first = substr($name, 0, $pos);
            if (!array_key_exists($first, $array)) {
                $array[$first] = array();
            }

            $child = trim(substr($name, $pos), '[]');
            if ($child) {
                self::_ensure_exists($array[$first], $child);
            }
        } else {
            if (!array_key_exists($name, $array)) {
                $array[$name] = '';
            }
        }
    }

    public function render_group($name, $value, $control, $label, $help = null, $options = array())
    {
        $control_html = self::render_control($name, $value, $control, $label, $help, $options);
        return HtmlUtil::render_tag('div', array('class' => 'form-group'), $control_html);
    }

    public function render_control($name, $value, $control, $label, $help = null, $options = array())
    {
        $label_html = self::render_label($label, array('for' => $name));
        $help_html = $help ? self::render_help($help) : null;

        $control_method = 'render_' . $control;
        $control_html = $this->$control_method($name, $value, $options);

        $hidden_html = self::render_hidden(self::$controls_hidden_name . '[]', $name);
        return $label_html . $control_html . $help_html . $hidden_html;
    }

    public function render_label($label, $options = array())
    {
        $attributes['class'] = 'control-label';
        $attributes = array_merge($attributes, $options);
        return HtmlUtil::render_tag('label', $attributes, $label . '：');
    }

    public function render_help($help, $options = array())
    {
        $attributes['class'] = 'help-block';
        $attributes = array_merge($attributes, $options);
        return HtmlUtil::render_tag('span', $attributes, $help);
    }

    public function render_button($text, $icon, $class, $options = array())
    {
        $icon_html = $icon ? HtmlUtil::render_tag('i', array('class' => $icon)) : null;

        $attributes['type'] = 'button';
        $attributes['class'] = $class;
        $attributes = array_merge($attributes, $options);
        return HtmlUtil::render_tag('button', $attributes, $icon_html . '&nbsp;&nbsp;' . $text . '&nbsp;&nbsp;');
    }

    public function render_submit_and_cancel($submit_url, $cancel_url)
    {
        $submit_html = self::render_button('确定', null, 'btn btn-primary btn-submit ajax-post require-validate loading-icon', array('url' => $submit_url));
        $cancel_html = self::render_button('取消', null, 'btn btn-default btn-cancel redirect', array('url' => $cancel_url));
        return HtmlUtil::render_tag('div', array('class' => 'form-group form-actions'), $submit_html . '&nbsp;' . $cancel_html);
    }

    private static function _render_input($type, $name, $value, $attributes = array())
    {
        $attributes['type'] = $type;
        $name !== null && $attributes['name'] = $name;
        $value !== null && $attributes['value'] = $value;
        return HtmlUtil::render_tag('input', $attributes);
    }

    public static function render_hidden($name, $value, $options = array())
    {
        return self::_render_input('hidden', $name, $value, $options);
    }

    private static function _format_cid($name)
    {
        return str_replace(array('[', ']'), '_', $name);
    }

    public static function render_text($name, $value, $options = array())
    {
        $attributes['class'] = 'form-control';
        $attributes = array_merge($attributes, $options);
        return self::_render_input('text', $name, $value, $attributes);
    }

    public function render_password($name, $value, $options = array())
    {
        $attributes['class'] = 'form-control';
        $attributes = array_merge($attributes, $options);
        return $this->_render_input('password', $name, $value, $attributes);
    }

    public function render_url($name, $value, $options = array())
    {
        $attributes['class'] = 'form-control';
        $attributes = array_merge($attributes, $options);
        return $this->_render_input('url', $name, $value, $attributes);
    }

    public function render_email($name, $value, $options = array())
    {
        $attributes['class'] = 'form-control';
        $attributes = array_merge($attributes, $options);
        return $this->_render_input('email',$name, $value, $attributes);
    }

    public function render_decimal($name, $value, $options = array())
    {
        $attributes['class'] = 'form-control format format-decimal';
        $attributes = array_merge($attributes, $options);
        return self::_render_input('text', $name, $value, $attributes);
    }

    public function render_number($name, $value, $options = array())
    {
        $attributes['class'] = 'form-control format format-number';
        $attributes = array_merge($attributes, $options);
        return $this->_render_input('text', $name, $value, $attributes);
    }

    public function render_textarea($name, $value, $options = array())
    {
        $attributes['name'] = $name;
        $attributes['class'] = 'form-control';
        $attributes['rows'] = 10;
        $attributes = array_merge($attributes, $options);
        return HtmlUtil::render_tag('textarea', $attributes, $value);
    }

    public function render_switch($name, $value, $options = array())
    {
        $attributes['type'] = 'checkbox';
        $attributes['switch-ref'] = $name;
        $value && $attributes['checked'] = 'checked';
        $attributes = array_merge($attributes, $options);
        $input_html = HtmlUtil::render_tag('input', $attributes);
        $hidden_html = self::render_hidden($name, $value);
        return HtmlUtil::render_tag('div', array('class' => 'sf-switch'), $input_html) . $hidden_html;
    }

    public function render_status($name, $value, $options = array())
    {
        return $this->render_switch($name, $value, $options);
    }

    public function render_date($name, $value, $options = array())
    {
        $attributes['class'] = 'form-control';
        $attributes['control'] = 'datetime-picker';
        $attributes['data-format'] = config('SYS_DATE_FORMAT');
        $attributes['value'] = $value;
        $attributes = array_merge($attributes, $options);
        return $this->_render_input('text', $name, $value, $attributes);
    }

    public function render_date_ts($name, $value, $options = array())
    {
        $attributes['class'] = 'form-control';
        $attributes['control'] = 'datetime-picker';
        $attributes['ref-hidden'] = $this->_format_cid($name);
        $attributes['data-format'] = config('SYS_DATE_FORMAT');
        $attributes['value'] = sf_format_date($value);
        $attributes = array_merge($attributes, $options);
        $input_html = HtmlUtil::render_tag('input', $attributes);
        $hidden_html = $this->render_hidden($name, $value, array('hidden-id' => $this->_format_cid($name)));
        return $input_html . $hidden_html;
    }

    public function render_html($name, $value, $options = array())
    {
        $attributes['control'] = 'summernote';
        $attributes['ref-hidden'] = $this->_format_cid($name);
        $attributes['data-height'] = '300';
        $attributes = array_merge($attributes, $options);
        $div_html = HtmlUtil::render_tag('div', $attributes, $value);
        $hidden_html = $this->render_hidden($name, $value, array('hidden-id' => $this->_format_cid($name)));
        return $div_html . $hidden_html;
    }

    public function render_image($name, $value, $options = array())
    {
        //$options['data-preview-file-type'] = 'image';
        //$options['data-allowed-file-types'] = 'image';
        //$options['data-allowed-file-extensions'] = 'gif';
        return $this->render_file($name, $value, $options);
    }

    public function render_file($name, $value, $options = array())
    {
        $attributes['type'] = 'file';
        $attributes['control'] = 'bootstrap-fileinput';
        $attributes['ref-hidden'] = $this->_format_cid($name);
        $attributes['data-max-file-count'] = 1;
        list($file_ids, $file_list) = $this->_getFileList($value);
        $attributes['initial-file-list'] = $file_list;
        $attributes = array_merge($attributes, $options);
        $input_html = HtmlUtil::render_tag('input', $attributes);
        $hidden_html = $this->render_hidden($name, $file_ids, array('hidden-id' => $this->_format_cid($name)));
        return $input_html . $hidden_html;
    }

    private function _getFileList($value)
    {
        $file_list = array();
        $file_ids = array();
        foreach (explode(',', $value) as $file_id) {
            $file_info = model('admin/upload')->getFileInfo($file_id);
            if ($file_info) {
                $file_ids[] = $file_info['id'];
                $file_list[] = implode(',', array($file_info['id'], $file_info['name'], $file_info['size'], $file_info['url']));
            }
        }
        return array(implode(',', $file_ids), implode(';', $file_list));
    }

    public function render_select($name, $value, $options = array())
    {
        if (isset($options['list'])) {
            $list = $options['list'];
            unset($options['list']);

            if (is_string($list)) {
                $list = model('admin/option')->get_options_array($list);
            }
        } else {
            $list = array();
        }

        $attributes['name'] = $name;
        $attributes['class'] = 'form-control';
        $attributes['placeholder'] = '请选择';
        $attributes['control'] = 'select2';
        $attributes = array_merge($attributes, $options);
        $html = HtmlUtil::render_start_tag('select', $attributes);
        //$html .= $this->_render_option($value, '0', '');
        $html .= HtmlUtil::render_tag('option');

        foreach (array_keys($list) as $key) {
            $html .= $this->_render_option($value, $key, $list[$key]);
        }

        $html .= HtmlUtil::render_end_tag('select');
        return $html;
    }

    private function _render_option($select_value, $opt_key, $opt_label)
    {
        $attributes['value'] = $opt_key;
        if ($select_value == $opt_key) {
            $attributes['selected '] = 'selected ';
        }
        return HtmlUtil::render_tag('option', $attributes, $opt_label);
    }

    public function render_checklist($name, $value, $options = array())
    {
        if (isset($options['list'])) {
            $list = (array) $options['list'];
            unset($options['list']);
        } else {
            $list = array();
        }

        $attributes['class'] = 'checklist-control';
        $attributes = array_merge($attributes, $options);
        $html = HtmlUtil::render_start_tag('div', $attributes);
        $html .= HtmlUtil::render_start_tag('div', array('class' => 'checklist-box'));

        foreach (array_keys($list) as $key) {
            $html .= HtmlUtil::render_start_tag('div', ['class' => 'checkbox']);
            $html .= HtmlUtil::render_start_tag('label');
            $checked = in_array($key, $list);
            $html .= $this->_render_input('checkbox', $name . '[]', $key, in_array($key, (array) $value) ? array('checked' => 'checked') : null);
            $html .= $list[$key];
            $html .= HtmlUtil::render_end_tag('label');
            $html .= HtmlUtil::render_end_tag('div');
        }

        $html .= HtmlUtil::render_end_tag('div');

        $html .= HtmlUtil::render_start_tag('div', array('class' => 'checklist-actions'));
        $html .= AdminHtml::render_button('选择全部', null, 'btn btn-link select-all');
        $html .= ' / ';
        $html .= AdminHtml::render_button('取消选择', null, 'btn btn-link unselect-all');
        $html .= HtmlUtil::render_end_tag('div');

        $html .= HtmlUtil::render_end_tag('div');
        return $html;
    }
}